﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting;
using System.Runtime.InteropServices;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.ComponentModel;
using System.Reflection;
using System.Collections;
using System.Linq.Expressions;
using System.ServiceModel.Description;

using TDB.Client;
using TDB.LinqSerializer;

namespace TDB
{
  public class DocumentStore
  {
    public static string DefaultServerUri { get; set; }
    public static string DefaultStoreName { get; set; }

    private TDB.Administration.AdministrationServicesClient adminClient = null;
    private TDB.CommandService.CommandServiceClient commandClient = null;
    private TDB.QueryService.QueryServiceClient queryClient = null;

    public string StoreName { get; set; }

    public DocumentStore()
    {
      adminClient = new Administration.AdministrationServicesClient();
      commandClient = new CommandService.CommandServiceClient();
      queryClient = new QueryService.QueryServiceClient();

      ContractDescription cd = commandClient.Endpoint.Contract;
      foreach (var op in cd.Operations)
      {
        DataContractSerializerOperationBehavior serializerBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
        if (serializerBehavior != null)
          serializerBehavior.DataContractResolver = new TypeResolver();
      }
    }

    public void SetCollection<T>(IEnumerable<T> entities)
    {
      List<object> ll = new List<object>();
      foreach (var e in entities) ll.Add(e);
      commandClient.SetCollection(StoreName, ll.ToArray());
    }

    public void Set<T>(T entity)
    {
      commandClient.Set(StoreName, entity);
    }

    public IEnumerable Get<T>(Expression<Func<T, bool>> expression)
    {
      var xml = expression.Serialize();
      return queryClient.XGet(StoreName, xml);
    }

    [Description("Validate Object for DataBase. This method check if the object is correctly storable in the DB")]
    public static bool ValidateObject(object obj, out Exception ex)
    {
      try
      {
        ex = null;
        MemoryStream ms = new MemoryStream();
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(ms, obj);
      }
      catch (Exception e)
      {
        ex = e;
        return false;
      }
      return true;
    }

    [Description("Validate Object for DataBase. This method check if the object is correctly storable in the DB")]
    public static bool ValidateObject(object obj)
    {
      try
      {
        MemoryStream ms = new MemoryStream();
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(ms, obj);
      }
      catch (Exception e)
      {
        return false;
      }
      return true;
    }
  }
}
